package app.tool;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.rygh.core.html.Html;
import org.rygh.core.html.UHtml;
import org.rygh.core.html.table.HtmlTable;
import org.rygh.core.html.table.TableData;
import org.rygh.core.html.table.TableTuple;
import org.rygh.core.util.UIo;
import org.rygh.core.util.UMath;
import org.rygh.core.util.UTime;
import org.rygh.core.util.counter.IntegerSpanner;
import org.rygh.semantic.jena.DbIterator;
import org.rygh.semantic.jena.SDatabase;
import org.rygh.semantic.model.ex.Degreer;
import org.rygh.semantic.model.rdf.Entity;
import org.rygh.semantic.sparql.ResultTuple;
import org.rygh.semantic.sparql.SparQL;

import wsi.exp.ExpFolderController;
import wsi.script.AppConfig;
import wsi.script.QueryTuple;
import app.App;

public class degreeDist extends App {

	public static void main(String[] args) {
		init();
		AppConfig.init(args[0]);

		String res = run();

		File dir = ExpFolderController.shared().getFolderForExp0();

		UIo.saveFile(
				new File(dir, String.format("degree_distribution_%s_%s.html",
						AppConfig.shared().getKnowledgeDatabase(),
						UTime.toLogString())), res);

		bye();
	}

	private static String run() {
		AppConfig config = AppConfig.shared();
		System.out.println("db: " + config.getKnowledgeDatabase());

		TableData data = new TableData();
		TableTuple tuple = new TableTuple();

		tuple.add("Query", "Content", "# Entity", "Max Degree", "Mean Degree",
				"Min Degree", "Distribution");
		data.add(tuple);

		List<Integer> ints = new ArrayList<>();
		Degreer deg = new Degreer();
		IntegerSpanner span;

		Map<String, QueryTuple> queryMap = config.getQueryMap();
		int min, max, size;
		double avg;
		int dmax, M = 1_000_000;

		for (Entry<String, QueryTuple> e : queryMap.entrySet()) {
			String key = e.getKey();

			dmax = config.getDegreeMax(key);

			System.out.printf("query: %s, degree max: %d\n", key, dmax);

			size = 0;
			ints.clear();
			min = Integer.MAX_VALUE;
			max = Integer.MIN_VALUE;

			tuple = new TableTuple();
			tuple.add(key);
			tuple.add(UHtml.escape(e.getValue().toString()));

			SparQL query = e.getValue().getQuery();
			query.setLimit(-1);

			DbIterator iter = SDatabase.shared().iterator();

			iter.begin(query);
			ResultTuple m;

			while ((m = iter.next()) != null) {
				if (m.isEmpty())
					continue;

				size++;

				if (size % (M / 10) == 0)
					System.out.printf("size: %.2fm\r", 1. * size / M);
				else if (size % (M / 100) == 0)
					System.out.print('.');

				Entity entity = m.getX();

				int d = deg.getDegree(entity);

				if (dmax > 0 && d > dmax)
					continue;

				if (min > d)
					min = d;

				if (max < d)
					max = d;

				ints.add(d);
			}

			iter.end();

			tuple.add(size);
			avg = UMath.getAverage(ints, 0);
			tuple.add(max);
			tuple.add(String.format("%.2f", avg));
			tuple.add(min);

			span = new IntegerSpanner(min, max, 10);

			for (int v : ints)
				span.count(v);

			tuple.add(span.toHtmlTable().toSimpleString());

			data.add(tuple);
		}

		String title = String.format("Degree Distribution (%s)", AppConfig
				.shared().getKnowledgeDatabase());

		Html html = new Html(title);
		html.addElement(new HtmlTable(title, data, false));

		return html.toString();
	}
}
